package com.winit.deploy.task.tomcatTask;

import com.winit.common.util.ShellRunUtil;
import com.winit.common.util.SpringContextHolder;
import com.winit.core.server.factory.LinuxJumpServerFactory;
import com.winit.core.task.Task;
import com.winit.deploy.bean.WinitTomcatInfo;
import com.winit.deploy.manager.DeployManager;
import com.winit.deploy.server.WinitJumpServer;
import com.winit.deploy.server.WinitTomcatServer;
import com.winit.project.core.bean.PackageTypeEnum;
import com.winit.project.core.branch.Project;
import com.winit.project.core.edition.PackageEdition;
import com.winit.project.core.set.ProjectSetConfig;
import com.winit.project.util.ProjectUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

/**
 * Created by wangjian on 16/8/10.
 * 发布任务step1 准备
 * 1.机器是否已经初始化
 *
 * 1.检出配置文件
 * 1.校验配置文件是否正确
 * 4.生成war包
 *
 * 5.beetle机器或跳板机向终端机推送war包
 * 6.校验终端机war包是否推送成功(文件是否存在)
 */
public class DeployPrepareTask extends Task {

    static final Logger logger = LoggerFactory.getLogger(DeployPrepareTask.class);

    /**
     * 跳板机
     * 用于推送war包
     */
    private WinitJumpServer winitJumpServer = null;
    /**
     * 远程终端机,用于校验war是否推送成功
     */
    private WinitTomcatServer winitTomcatServer;
    /**
     * 必传
     */
    private WinitTomcatInfo winitTomcatInfo;

    /**
     * 使用beetle本机推送war包
     * @param taskId
     * @param expireTime
     * @param winitTomcatServer
     */
    public DeployPrepareTask(String taskId, Integer expireTime,WinitTomcatServer winitTomcatServer,WinitTomcatInfo winitTomcatInfo){
        super(taskId, expireTime);
        this.winitTomcatServer = winitTomcatServer;
        this.winitTomcatInfo = winitTomcatInfo;
    }

    /**
     * 使用跳板机推送war包
     * @param taskId
     * @param expireTime
     * @param winitTomcatServer
     * @param winitJumpServer
     */
    public DeployPrepareTask(String taskId, Integer expireTime,WinitTomcatServer winitTomcatServer,WinitJumpServer winitJumpServer,WinitTomcatInfo winitTomcatInfo){
        super(taskId, expireTime);
        this.winitTomcatServer = winitTomcatServer;
        this.winitJumpServer = winitJumpServer;
        this.winitTomcatInfo = winitTomcatInfo;
    }

    @Override
    public TaskStatus call() throws Exception {
        logger.info("com.winit.deploy.task.tomcatTask.DeployPrepareTask.call start taskId="+this.taskId);
        String projectName = this.winitTomcatInfo.getProjectName();
        String editionNum = this.winitTomcatInfo.getEditionNum();

        StringBuffer errorStr = new StringBuffer();

        //2.war包临时存放目录是否存在  校验tomcat相关路径
        try {
            String percent = this.winitTomcatServer.getPercentOfSpace();
            if("100".equals(percent)){
                errorStr.append("<br>终端空间已满,请先清理后再进行发布!");
            }
        }catch (Exception e){
            errorStr.append("<br>检验终端空间剩余,").append(e.getMessage());
        }
        try {
            this.winitTomcatServer.isPathExist(this.winitTomcatInfo.getWarTempDir(),true,false);
        }catch (Exception e){
            errorStr.append("<br>校验war包临时存放目录,").append(e.getMessage());
        }
        try {
            this.winitTomcatServer.isPathExist(this.winitTomcatInfo.getServerPath(),false,false);
        }catch (Exception e){
            errorStr.append("<br>校验tomcat目录,").append(e.getMessage());
        }
        try {
            this.winitTomcatServer.isPathExist(this.winitTomcatInfo.getProjectDir(),false,false);
        }catch (Exception e){
            errorStr.append("<br>校验工程目录,").append(e.getMessage());
        }
        try {
            this.winitTomcatServer.isPathExist(this.winitTomcatInfo.getServerPath()+"/webapps",false,false);
        }catch (Exception e){
            errorStr.append("<br>校验工程备份目录,").append(e.getMessage());
        }
        try {
            this.winitTomcatServer.isPathExist(this.winitTomcatInfo.getServerPath()+"/tomcat.sh",false,false);
        }catch (Exception e){
            errorStr.append("<br>校验tomcat.sh脚本是否存在,").append(e.getMessage());
        }
        //3.判断tomcat目录权限
        try {
            this.winitTomcatServer.checkTomcatPermisson();
        }catch (Exception e){
            errorStr.append("<br>").append(e.getMessage());
        }

        DeployManager deployManager = SpringContextHolder.getBean(DeployManager.class);
        //4.校验配置文件
        try {
            deployManager.deployPrepare(this.winitTomcatInfo,this.taskId);
            //不使用跳板机时,在本地生成war包
            if (this.winitJumpServer == null) {
                Project project = new Project(projectName, true);
                ProjectSetConfig setConfig = project.getProjectSetConfig();
                PackageEdition edition = new PackageEdition(projectName, editionNum, true);
                String warPath = ProjectUtil.getProjectFilePath(projectName) + editionNum + "/target/" + edition.getPackageEditionConfig().getNasNum()
                        + "/" + setConfig.getWarName() + ".war";
                String warName = this.winitTomcatInfo.getWarName();
                ProjectUtil.replaceConfigFile(PackageTypeEnum.MAVEN_WAR, ProjectUtil.getProjectFilePath(projectName) + editionNum + "/release" + "/" + this.taskId
                        , this.winitTomcatInfo.getWarPath().replace(warName + ".war", "")
                        , warPath, warName, project.getProjectConfig().getConfigPath(), this.winitTomcatInfo.isVmEnv());
            }
        }catch (Exception e){
            errorStr.append("<br>校验配置文件,").append(e.getMessage());
        }

        if(!StringUtils.isEmpty(errorStr.toString())){
            throw new Exception(errorStr.toString());
        }

        //当前task发布使用的war包存放目录
        String releaseTempPath = this.winitTomcatInfo.getWarPath().replace(this.winitTomcatInfo.getWarName()+".war","");
        try {
            //5.推送tomcat.sh脚本
            this.pushTomcatsh();

            if(this.winitJumpServer != null){
                //需要使用跳板机时,先将config包从本地推送到跳板机,然后再从跳板机推送至终端
                this.winitJumpServer.deldirs(releaseTempPath);
                this.winitJumpServer.mkdirs(releaseTempPath);
                //推送环境配置文件包至跳板机
                pushToJump(releaseTempPath);
                //在跳板机上生成发布war包
                String editionPath = ProjectUtil.getProjectFilePath(this.winitTomcatInfo.getProjectName())+
                        this.winitTomcatInfo.getEditionNum();
                PackageEdition edition = new PackageEdition(projectName,editionNum,true);
                String nasNum = ProjectUtil.getEditionNasNum(edition.getPath());
                this.winitJumpServer.createWarPackage(PackageTypeEnum.MAVEN_WAR,releaseTempPath,editionPath,this.taskId,this.winitTomcatInfo.getWarName(),nasNum,"");
                //推送war包至终端机
                this.winitJumpServer.doPush(this.winitTomcatInfo.getWarPath(),this.winitTomcatInfo.getWarTempDir()+"/"+this.winitTomcatInfo.getWarName()+".war"
                        ,this.winitTomcatInfo.getServerIp(),this.winitTomcatInfo.getSshPort());
            }else{
                this.doPush();
            }
            this.winitTomcatServer.doCheckWar();

        }catch (Exception e){
            throw e;
        }finally {
        }

        logger.info("com.winit.deploy.task.tomcatTask.DeployPrepareTask.call end taskId="+this.taskId);
        return TaskStatus.STATUS_SUCCESS;
    }

    /**
     * 从beetle本机推送
     * @return
     * @throws Exception
     */
    private void doPush() throws Exception{
        String str = this.pushFromLocal(this.winitTomcatInfo.getSshPort(),this.winitTomcatInfo.getWarPath(),
                this.winitTomcatInfo.getUserName()+"@"+this.winitTomcatInfo.getServerIp()+":"+this.winitTomcatInfo.getWarTempDir()+"/"+this.winitTomcatInfo.getWarName()+".war");
        logger.info("DeployPrepareTask:从beetle本机推送war包,返回:"+str);
        if(!StringUtils.isEmpty(str)){
            throw new Exception("DeployPrepareTask:从beetle本机推送war包失败,"+str);
        }
    }

    private void pushToJump(String releaseTempPath) throws Exception{
        String evnConfigTarPath = ProjectUtil.getProjectFilePath(this.winitTomcatInfo.getProjectName())+
                this.winitTomcatInfo.getEditionNum()+"/release/"+this.taskId+".tgz";
        String level = this.winitJumpServer.getLevel();
        if("1".equals(level)){
            pushToLevelOneFromLocal(evnConfigTarPath,releaseTempPath,this.winitJumpServer.getIp()
                    ,String.valueOf(this.winitJumpServer.getServerPort()));
        }else{
            WinitJumpServer levelOne = LinuxJumpServerFactory.getInstance().getParentServer(this.winitJumpServer.getIp());
            levelOne.deldirs(releaseTempPath);
            levelOne.mkdirs(releaseTempPath);
            pushToLevelOneFromLocal(evnConfigTarPath,releaseTempPath,levelOne.getIp(),String.valueOf(levelOne.getServerPort()));
            levelOne.doPush(releaseTempPath+this.taskId+".tgz",releaseTempPath+"/",this.winitJumpServer.getIp()
                    , String.valueOf(this.winitJumpServer.getServerPort()));
        }
    }

    /**
     *将环境配置文件压缩包推送至一级跳板机
     * @param evnConfigTarPath 环境配置文件压缩包路径 在版本目录下
     * @param releaseTempPath 当前task发布包路径存放目录
     * @param ip
     * @param port
     * @throws Exception
     */
    private void pushToLevelOneFromLocal(String evnConfigTarPath,String releaseTempPath,String ip,String port) throws Exception{
        String str = this.pushFromLocal(port,evnConfigTarPath,this.winitTomcatInfo.getUserName()+"@"+ip+":"+releaseTempPath);
        logger.info("DeployPrepareTask:从beetle本机推送war包至跳板机,返回:"+str);
        if(!StringUtils.isEmpty(str)){
            throw new Exception("DeployPrepareTask:从beetle本机推送war包至跳板机失败,"+str);
        }
    }

    private void pushTomcatsh() throws Exception{
        if(this.winitJumpServer != null){
            //从跳板机上推送
            this.winitJumpServer.doPush("/home/beetle/shell/tomcat.sh",this.winitTomcatInfo.getServerPath()+"/"
                    ,this.winitTomcatInfo.getServerIp(),this.winitTomcatInfo.getSshPort());
        }else {
            //从本地推送
            String tomcatShPath = Thread.currentThread().getContextClassLoader().getResource("").getPath()+"shell/init/tomcat.sh";
            String str = this.pushFromLocal(this.winitTomcatInfo.getSshPort(),tomcatShPath,this.winitTomcatInfo.getUserName()+"@"+this.winitTomcatInfo.getServerIp()+":"+this.winitTomcatInfo.getServerPath()+"/");
            if(!StringUtils.isEmpty(str)){
                throw new Exception("DeployPrepareTask:从beetle本机推送tomcat.sh失败,"+str);
            }
        }
    }

    private String pushFromLocal(String port,String fromPath,String toPath){
        String[] param = new String[7];
        param[0] = "scp";
        param[1] = "-i";
        param[2] = this.winitTomcatInfo.getKeyFilePath();
        param[3] = "-P";
        param[4] = port;
        param[5] = fromPath;
        param[6] = toPath;
        String str = ShellRunUtil.runShell(param);
        logger.info("com.winit.deploy.task.tomcatTask.DeployPrepareTask.pushFromLocal str="+str);
        return str;
    }

}
